package kim.artemis.rpc.core.protocol.server;

import kim.artemis.rpc.core.annotation.ArtemisRpcService;
import kim.artemis.rpc.core.common.enums.ServiceRegistryEnum;
import kim.artemis.rpc.core.common.exception.ArtemisException;
import kim.artemis.rpc.core.registry.ServiceRegistry;
import kim.artemis.rpc.core.protocol.serializer.ArtemisSerializer;
import kim.artemis.rpc.core.common.enums.SerializerEnum;
import kim.artemis.rpc.core.util.ArtemisProxyUtils;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.util.Map;

/**
 * 服务工厂
 * @author Wq.
 */
@Slf4j
public class ArtemisRpcServerFactory extends ArtemisRpcServer implements ApplicationContextAware, InitializingBean, DisposableBean {

    /**
     * 注册中心地址
     */
    @Setter
    private String address;

    /**
     * 端口
     */
    @Setter
    private int port;

    /**
     * 令牌
     */
    @Setter
    private String accessToken;

    /**
     * 序列化方式
     * 默认 Kryo
     */
    @Setter
    private String serializer = SerializerEnum.Kryo.name();

    /**
     * 服务注册方式
     * 默认 Zookeeper
     */
    @Setter
    private String registry = ServiceRegistryEnum.Zookeeper.name();


    public void initServer () {
        // 初始化序列化方式
        SerializerEnum serializerEnum = SerializerEnum.match(serializer, null);
        ArtemisSerializer artemisSerializer = null != serializerEnum ? serializerEnum.getSerializer() : null;

        // 初始化注册中心
        ServiceRegistryEnum serviceRegistryEnum = ServiceRegistryEnum.match(registry, null);
        Class<? extends ServiceRegistry> serviceRegistry = null != serviceRegistryEnum ? serviceRegistryEnum.getServiceRegistry(): null;

        // 启动化服务端
        super.start(address, port, accessToken, artemisSerializer, serviceRegistry);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        this.initServer();
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, Object> serviceBeanMap = applicationContext.getBeansWithAnnotation(ArtemisRpcService.class);
        if (null != serviceBeanMap &&  0 < serviceBeanMap.size()) {
            for (Object serviceBean : serviceBeanMap.values()) {
                // 获取真实对象
                serviceBean = ArtemisProxyUtils.getTarget(serviceBean);
                if (0 == serviceBean.getClass().getInterfaces().length) {
                    throw new ArtemisException("artemis rpc, service(ArtemisRpcService) must inherit interface.");
                }
                ArtemisRpcService artemisRpcService = serviceBean.getClass().getAnnotation(ArtemisRpcService.class);
                String interfaces = serviceBean.getClass().getInterfaces()[0].getName();
                String version = artemisRpcService.version();
                // 注册service
                super.pushService(interfaces, version, serviceBean);
            }
        }
    }

    @Override
    public void destroy() throws Exception {
        super.stop();
    }

}
